#fcja generuje losowa macierz o rozmiarze x na x
genMatrix<-function(x) {
	ret<-matrix(floor(5*x*runif(x*x))+1,x,x)
	ret[matrix(c(1:x,1:x),x,2)]<-Inf
	return(ret)
}


#argumentem funkcji jest nazwa przestrzeni problemu
bf.initProblem<-function(x) {
	cost<<-function(...) do.call(paste(x,".cost",sep=""),list(...))
	heuristic<<-function(...) do.call(paste(x,".heuristic",sep=""),list(...))
	init<<-function(...) do.call(paste(x,".init",sep=""),list(...))
	generate<<-function(...) do.call(paste(x,".generate",sep=""),list(...))	
}


bf.op_init<-function(UG){
	x <- UG
	return(init(x))
}

#wybiera indeks elementu minimalnego
bf.findmin<-function() {
	return(which(min(costs[open])==costs&open)[1])
}

# selekcja - wybiera jeden, najlepszy punkt
bf.op_select<-function(XS, UG) {
	minindex<-bf.findmin()
	open[minindex]<<-FALSE
	return (XS[[minindex]])
}

# generacja - w metodzie best_first punkty generowane sa na podstawie
#pojedynczego wczesniej wybranego wariantu, przy okazji
bf.op_generate<-function(XS,UG) {
	#selected <- XS[[1]]
	selected <- XS

	return(generate(selected))
}

#w algorytmie best_first kryterium zatrzymania odpowiada sytuacji
#gdy najlepszy z kandydatow jest juz w pelni zewaluowany tj. H(x)==0
bf.stop_criterion<-function(XS, stop_args=NULL) {
	minindex<-bf.findmin()
	if(heuristic(trace[[minindex]])==0){
		print(trace[[minindex]])
		result<<-list()
		result[[1]]<<-trace[[minindex]]
		result[[2]]<<-cost(result[[1]])
		return(TRUE)
	}
	return(FALSE)
}


#wywolujemy tak:
#inicjalizujemy zmienna tsp.task tudziez sort.task
#posilkujac sie np fcjami genMatrix czy genSequence
#a nastepnie wywolujemy bf.search("tsp") lub bf.search("sort")
bf.search <- function(x) {
	bf.initProblem(x)
	search(bf.op_init, bf.op_select,bf.op_generate, bf.stop_criterion, UG)
}
